namespace CLELCore.Collections
{
	public class Heap
	{
		private HeapItem [] _items;
		//total byte size
		private int _size;
		//index of last used
		private int _used;

		public int Size
		{
			get
			{
				return _size;
			}
		}
		
		private void Resize()
		{
			int size = 0;
			if(_items == null)
			{
				size = 13;
			}
			else
			{
				size = _items.Length * 2;
			}
			HeapItem [] new_items = new HeapItem[size];
			if(_used > 0)
			{
				int i;
				for(i = 0;i < _used;i++)
				{
					new_items[i] = _items[i];
				}
			}
			_items = new_items;
		}

		public Heap()
		{
			_size = 0;
			_used = 0;
			Resize();
		}

		public int Malloc(int size)
		{
			if(size > 0)
			{
				HeapItem item = new HeapItem(size);
				if(_used >= _items.Length)
					Resize();
				_items[_used] = item;
				_used++;
				int prev_size = _size;
				_size += size;
				return prev_size;
			}

			return -1;
		}
		
		public int Resize(int off,int len)
		{
			if(off >= 0 && len > 0)
			{
				int i,j;
				int size = 0;
				byte [] new_val;
				byte [] old_val;
				int old_size;
				for(i = 0;i < _used;i++)
				{
					if(size == off)
					{
						old_size = _items[i].Size;
						new_val = new byte[len];
						old_val = _items[i].Item;
						for(j = 0;j < len && j < old_size;j++)
							new_val[j] = old_val[j];
						_size -= old_size;
						_size += len;
						_items[i].Item = new_val;
						return old_size;
						
					}
					size += _items[i].Size;
				}
			}
			return 0;
		}

		public void Free(int off)
		{
			if(_items != null && off >= 0)
			{
				int i;
				int size = 0;
				for(i = 0;i < _used;i++)
				{
					if(size == off)
					{
						_items[i].Free = true;
					}
					size += _items[i].Size;
				}
			}
		}

		public bool Set(int off,byte [] val)
		{
			if(_items != null && off >= 0 && val != null)
			{
				int i;
				int size = 0;
				for(i = 0;i < _used;i++)
				{
					if(size == off && _items[i].Free == false)
					{
						byte [] item_val = _items[i].Item;
						int j;
						for(j = 0;j < item_val.Length && j < val.Length;j++)
						{
							item_val[j] = val[j];
						}
						return true;
					}
					size += _items[i].Size;
				}
			}
			return false;
		}

		public int[][] Compress()
		{
			if(_items != null)
			{
				int [][] ret = new int[_used][];
				int i;
				for(i = 0;i < ret.Length;i++)
					ret[i] = new int[2];
				int size = 0;
				for(i = 0;i < _used;i++)
				{
					ret[i][0] = size;
					size += _items[i].Size;
				}
				size = 0;
				for(i = 0;i < _used;i++)
				{
					if(_items[i].Free == false)
					{
						ret[i][1] = size;
						size += _items[i].Size;
					}
					else
						ret[i][1] = 0;
				}
				HeapItem [] items = new HeapItem[_items.Length];
				int j = 0;
				_size = 0;
				for(i = 0;i < _used;i++)
				{
					if(_items[i].Free == false)
					{
						items[j] = _items[i];
						_size += _items[i].Size;
						j++;
					}
				}
				_items = items;
				_used = j;
				return ret;
			}
			return null;
		}

		public byte[] Get(int off)
		{
			if(off >= 0 && off <_size && _items != null)
			{
				int i,j;
				int size = 0;
				for(i = 0;i < _used;i++)
				{
					if(size == off)
					{
						byte [] ret = new byte[_items[i].Size];
						byte [] val = _items[i].Item;
						for(j = 0;j < ret.Length;j++)
							ret[j] = val[j];
						return ret;
					}
					size += _items[i].Size;
				}
			}
			return null;
		}
	}
}
